Shembuj te POO

Shembujt qe ne paraqitem deri me tani jane shume te thjeshte ne krahasim me implementimet e jetes reale. Ne vazhdim do te paraqesim pak shembuj me te zgjeruar. E rendesishme eshte te kuptohet thelbi i programimit te orientuar nga objekti. Kompleksiteti varet nga sasia e veprimeve qe na duhet te bejme, por logjika eshte e njejte. Ne shembullin ne vazhdim do te ndertoj nderfaqe dhe klasa per kryerjen e disa veprimeve me punonjesit e nje kompanie. Shembull pak me i zgjeruar sesa ata qe trajtuam deri me tani, por gjithsesi mbetet i thjeshte.

Fillimisht le te ndertoj nje nderfaqe IPunonjes e cila do te jete si shabllon per klasen Punonjes. Ketu deklarojme metodat qe detyrimisht duhet te implementoje klasa Punonjes.

<?php

interface IPunonjes {

    public function getRrogaMujore();

}

Ndertojme nje klase Person e cila do te jete klase prind per klasen Punonjes:

<?php

class Person {

    public $id;
    public $emer;
    public $mbiemer;
    public $ditelindja;

    public function emriPlote() {
        return $this->emer . " " . $this->mbiemer; 
    }

}

Klasa Person permban atributet baze per nje person si id, emer, mbiemer, ditelindja. Shohim qe permban dhe nje metode emriPlote() e cila kthen emrin e plote duke bashkuar variablat anetare $this->emer dhe $this->mbiemer me nje hapesire ndermjet tyre.

Implementimi i klases Punonjes do te jete si me poshte:

<?php

class Punonjes extends Person implements IPunonjes {

    private $ore_pune_mujore = 168; // Ore
    private $pagesa_per_ore; // Leke

    private $ore_mungese = 0; // Ore
    private $ore_shtese = 0; // Ore

    public function getRrogaMujore() {
        return $this->pagesa_per_ore * $this->getOrePune();
    };

    public function getOrePune() {
        $this->ore_pune_mujore - $this->ore_mungese + $this->ore_shtese;
    }

    public function getPagesaPerOre() {
        return $this->pagesa_per_ore;
    }

    public function setPagesaPerOre(int $pagesa) {
        $this->pagesa_per_ore = $pagesa;
    }

    public function oreMungese(int $ore) {
        $this->ore_mungese += $ore;
    }

    public function oreShtese(int $ore) {
        $this->ore_shtese += $ore;
    }
}

Ne klasen Punonjes gjenden variablat anetare si ore_pune_mujore qe mban oret qe punon nje punonjes ne muaj, me nje vlere 168. Gjendet gjithashtu pagesa_per_ore, ore_mungese nese ka bere ndonje mungese gjate muajit, dhe ore_shtese nqs. ka punuar shtese gjate muajit. Metodat oreMungese(...) dhe oreShtese(...) bejne shtimin e vlerave te variablave ore_mungese dhe ore_shtese respektivisht duke perdorur operatorin += qe pervec vleres aktuale qe kane, i shtojne dhe vleren ne hyrje. Metoda setPagesaPerOre(...) i jep vlere variablit pagesa_per_ore.

Metoda getOrePune() llogarit oret e punes qe ka punuar nje punonjes duke marre oret totale, duke zbritur oret mungese, dhe duke shtuar oret shtese qe ai ka punuar. Metoda getRrogaMujore() thjesht ben nje llogaritje duke shumezuar pagesen per ore te nje punonjesi me oret qe ka bere ai kete muaj. Jemi te detyruar qe t'a implementojme funksionin getRrogaMujore pasi po perdorim nderfaqen IPunonjes e cila na detyron t'a bejme nje gje te tille, perndryshe do te gjenerohet gabim na PHP-ja.

Jo te gjithe punonjesit kane pozicione te njejta, ndaj le te ndertojme me specifikisht dy grupe punonjesisht Supervizor dhe Developer:

<?php

class Supervizor extends Punonjes {

    const PAGESA_PER_ORE = 900;

    function __construct() {
        $this->setPagesaPerOre(PAGESA_PER_ORE);
    }

}

class Developer extends Punonjes {
    const PAGESA_PER_ORE = 800;

    function __construct() {
        $this->setPagesaPerOre(PAGESA_PER_ORE);
    }
}

Per klasen Supervizor eshte krijuar nje konstante PAGESA_PER_ORE e cila mban pagesen per ore te ketij tipi punonjesi, aktualisht me vlere 900. E njejta gje edhe per klasen Developer por me nje vlere 800. Veme re qe per te dyja klasat, ne konstruktor eshte therritur metoda $this->setPagesaPerOre(PAGESA_PER_ORE); e cila trashegohet nga klasa Punonjes.

Le te bejme disa testime me klasat e mesiperme:

<?php

$supervizor = new Supervizor();

$supervizor->emri = "Brilant";
$supervizor->mbiemri = "Afmeti";

echo $supervizor->emriPlote() . " : " . $supervizor->getRrogaMujore();

Rezultati: Brilant Afmeti : 151200

Le te provojme te shtojme disa ore mungese per kete punonjes:

<?php

$supervizor->oreMungese(20);

echo $supervizor->emriPlote() . " : " . $supervizor->getRrogaMujore();

Rezultati: Brilant Afmeti : 133200

<?php

$developer = new Developer();

$developer->emri = "Alban";
$developer->mbiemri = "Afmeti";

echo $developer->emriPlote() . " : " . $developer->getRrogaMujore();

Rezultati: Alban Afmeti : 134400

Le te provojme te shtojme disa ore shtese disa here per kete punonjes:

<?php

$developer->oreShtese(4);
$developer->oreShtese(3);
$developer->oreShtese(5);

// Total: 12 ore shtese

echo $developer->emriPlote() . " : " . $developer->getRrogaMujore();

Rezultati: Alban Afmeti : 139200

Totalisht llogariten 12 ore shtese pavaresisht se jane vendosur ne therritje te ndryshme te metodes oreShtese(...). Arsye eshte se brenda kesaj metode kemi perdorur operatorin += te variablit anetare ore_shtese qe pervec vleres aktuale i shton dhe vleren e re te kaluar si argument ne metode.

Me poshte do te zgjerojme klasen Punonjes duke i shtuar disa anetare ne menyre qe te kemi mundesine te marrim ose te shtojme nje punonjes nga baza e te dhenave.

Fillimisht ndertojme nje klase Database e cila do te jete pergjegjese per veprimet qe kryhen me bazen e te dhenave.

<?php

class Database {

    public $connection;

    function __construct() {

        //Lidhemi me bazen e te dhenave
        $this->connect();
    }

    private function connect() {
        // Lidhemi me bazen e te dhenave, dhe do te na kthehet nje objekt qe mban lidhjen
        $this->connection = "Supozojme qe na kthehet nje objekt qe mban lidhjen me bazen e te dhenave!";
    }

    public function select(string $sql) {

        // Supozojme qe $connection eshte nje objekt qe ka disa metoda per te ndervepruar me bazen e te dhenave
        $rezultati = $this->connection->runSQL($sql);
        return $rezultati;
    }

    public function insert(string $table, array $values) {

        // Perdorim SQL per te shtuar nje rekord ne bazen e te dhenave
        // Supozojme qe SQL-ne e ndertuam
        $sql = "INSERT INTO $table VALUES...";

        $rezultati = $this->connection->runSQL($sql);
        return $rezultati;
    }


    public function update(string $table, array $values, string $where) {

        // Perdorim SQL per te modifikuar nje rekord ne bazen e te dhenave
        // Supozojme qe SQL-ne e ndertuam
        $sql = "UPDATE $table SET...";

        $rezultati = $this->connection->runSQL($sql);
        return $rezultati;
    }
}

Klasa Database ka nje variabel $connection e cila eshte do te mbaje nje reference per tek nje objekt. Ky objekt do te ndertohet pasi te therrasim metoden $this->connect(); ne konstruktor. Ne te vertete ne funksionin connect() i kemi dhene thjesht nje vlere string variablit $this->connection, por do te supozojme sikur kemi bere disa veprime dhe marrim mbrapsht nje objekt te lidhjes me databazen. Arsyeja pse e bera kete gje eshte per te mos humbur ne kod qe ne keto momente, pasi lidhjen me bazen e te dhenave do ta shpjegojme me hollesi me vone.

Nuk duhet te shqetesohemi per kete objekt pasi ne shume raste kur bejme veprime te ndryshme eshte vete PHP-ja qe na kthen objekte ne menyre qe te punojme me lehtesi. Edhe ne kete rast ky objekt duhet te nenkuptohet si nje lidhje me databazen qe na jep mundesine te kryejme veprime te ndryshme duke therritur metodat e ketij objekti. P.sh. do te supozojme qe ky objekt ka nje metode runSQL(...) e cila merr SQL ne hyrje, e ekzekuton ne databaze dhe na kthen pergjigje. Kujdes, kjo metode dhe ky objekt nuk ekziston ne te vertete tek ky rast, ky eshte thjeshte nje supozim!

Ne klasen Database gjenden disa metoda te rendesishme qe do t'i perdorim per te komunikuar me databazen si p.sh. metoda select(...) pranon SQL ne hyrje, dhe na kthen rekordet qe gjenden ne databaze. Metoda insert(...) pranon dy argumente, emrin e tabeles ne databaze dhe nje array associative (key => value) qe mban fushen e tabeles si celes, dhe vleren e fushes qe duam te ruajme si vlere. E njejta gje me metoden update(...), vetem se pranon nje argument te trete qe eshte kushti WHERE i SQL-se ne forme stringe. Keto metoda nuk jane te implementuara qe te funksionojne ne jeten reale, por i marrim te mireqena per arsye qe te shpjegojme sesi funksionon POO.

Me poshte po paraqesim anetaret qe i shtojme klases Punonjes. Pjeset qe i paraqitem me lart te kesaj klase, nuk po i paraqesim serish per arsye qe te jete me lehte per tu kuptuar dhe mos te behet shume kod.

<?php

class Punonjes extends Person implements IPunonjes {

    private $db;

    function __construct() {

        //Krijojme nje objekt te klases Database qe do ta shfrytezojme per te therritur metodat e saj si select, insert etj.
        $this->db = new Database();
    }


    public function getPunonjes($id) {
        $sql = "SELECT * FROM punonjesit WHERE id = $id";
        $punonjes = $this->db->select($sql);

        $this->emri = $punonjes['emri'];
        $this->mbiemri = $punonjes['mbiemri'];
        $this->ditelindja = $punonjes['ditelindja'];

        return $this;
    }

    public function shtoPunonjes(Punonjes $punonjes) {

        //Ndertojme nje array me vlerat e rekordit qe do te shtohet ne databaze
        $vlerat = [
            "emri" => $punonjes->emri,
            "mbiemri" => $punonjes->mbiemri,
            "ditelindja" => $punonjes->ditelindja,
        ];

        $rezultati = $this->db->insert("punonjesit", $vlerat);
        return $rezultati;
    }

}

Ne konstruktorin e klases Punonjes kemi krijuar nje instance te klases Database e cila ruhet ne variablin anetar $db. Ky objekt do te shfrytezohet qe te therrasim metodat e vlefshme si select(...), insert(...) etj.

Metoda getPunonjes(...) pranon ne hyrje nje id, ne menyre qe duke patur kete id ne mund te marrim nga baza e te dhenave punonjesin me kete id. Id-ja do te jete unike, ndaj ne jemi te sigurte qe punonjesi i cili do te na kthehet nga baza e te dhenave eshte i sakte:

<?php
public function getPunonjes($id) {
    $sql = "SELECT * FROM punonjesit WHERE id = $id";

    //Supozojme qe na kthen nje array associative
    $punonjes = $this->db->select($sql);

    $this->emri = $punonjes['emri'];
    $this->mbiemri = $punonjes['mbiemri'];
    $this->ditelindja = $punonjes['ditelindja'];

    return $this;
}

Do te futemi me vone ne detaje sesi funksionon SQL-ja, por momentalisht le ta marrim te mireqene qe variabli $sql mban SQL-ne e sakte per te marre nje rekord nga baza e te dhenave. Kete SQL e kalojme si argument tek metoda select(...) e objektit $db qe e aksesojme me $this->db dukeqenese eshte nje anetar i klases. Funksioni select(...) do te na ktheje si pergjigje rekordin me te dhenat per punonjesin ne nje array associative. Ruajme emrin, mbiemrin dhe ditelindjen tek objekti aktual dhe e kthejme ate me return $this.

Metoda shtoPunonjes pranon si argument nje objekt te tipit Punonjes. Kemi perdorur edhe 'Type Hinting' per t'u siguruar per dicka te tille. Ndertohet array associative $vlerat sepse nevojitet qe t'ja kalojme metodes insert(...). Me pas therrasim metoden $this->db->insert("punonjesit", $vlerat); duke i kaluar si argumente emrin e tabels dhe array-n associative qe sapo formuam. Rezultati qe kthehet $rezultati mund te jete ID e punonjesit te krijuar ne databaze, pasi ajo gjenerohet automatikisht nga databaza.

<?php


$punonjes = new Punonjes();
$punonjes->emri = "Alban";
$punonjes->mbiemri = "Alban";
$punonjes->ditelindja = "1991-12-06";

//Shtojme punonjesin ne bazen e te dhenave
$punonjes->shtoPunonjes($punonjes);        //Rezultati:    1

Pasi therrasim metoden shtoPunonjes(...) na kthehet rezultati 1 e cila eshte ID-ja e punonjesit me databaze. Provojme te marrim te dhenat e ketij punonjesi nga baza e te dhenave:

<?php

$punonjes = new Punonjes();

//Do te na ktheje nje instance te klases Punonjes
$punonjes = $punonjes->getPunonjes(1);

Me lart veme re qe punonjesin e shtuam me ane te deklarates $punonjes->shtoPunonjes($punonjes). Pra variablin $punonjes e perdorem per te therritur metoden, dhe e kaluam edhe si argument. Kjo gje mund te eleminohet duke e konvertuar ne nje funksion te tille $punonjes->shto(), si me poshte:

<?php

    public function shto() {

        //Ndertojme nje array me vlerat e rekordit qe do te shtohet ne databaze
        //Duke perdorur objektin aktual
        $vlerat = [
            "emri" => $this->emri,
            "mbiemri" => $this->mbiemri,
            "ditelindja" => $this->ditelindja,
        ];

        $rezultati = $this->db->insert("punonjesit", $vlerat);
        return $rezultati;
    }

Ne ndryshim nga me pare, ne kete rast po i marrim te dhenat qe do te ruajme ne databaze nepermjet objektit aktual perkatesisht $this->emri, $this->mbiemri dhe $this->ditelindja. Ne momentin qe shtojme nje punonjes mjafton te krijojme nje objekt te ri, te vendosim vlera per variablat anetare, dhe te therrsim metoden shto(), si me poshte:

<?php

$punonjes = new Punonjes();
$punonjes->emri = "Alban";
$punonjes->mbiemri = "Alban";
$punonjes->ditelindja = "1991-12-06";

$punonjes->shto();

Perdorimi i metodave statike per rastet e mesiperme

Metodat e klases Punonjes mund t'i konvertojme ne statike ne menyre qe shtimi i punonjesit dhe marrja nga databaza te behen ne forme tjeter. Bejme disa ndryshime te klasa Punonjes:

<?php

class Punonjes extends Person implements IPunonjes {

    private static $db;

    function __construct() {

        //Krijojme nje objekt te klases Database qe do ta shfrytezojme per te therritur metodat e saj si select, insert etj.
        self::db = new Database();
    }


    public static function getPunonjes($id) {
        $sql = "SELECT * FROM punonjesit WHERE id = $id";
        $punonjes = self::db->select($sql);

        $pun = new Punonjes();
        $pun->emri = $punonjes['emri'];
        $pun->mbiemri = $punonjes['mbiemri'];
        $pun->ditelindja = $punonjes['ditelindja'];

        return $pun;
    }

    public static function shtoPunonjes(Punonjes $punonjes) {

        //Ndertojme nje array me vlerat e rekordit qe do te shtohet ne databaze
        $vlerat = [
            "emri" => $punonjes->emri,
            "mbiemri" => $punonjes->mbiemri,
            "ditelindja" => $punonjes->ditelindja,
        ];

        $rezultati = self::db->insert("punonjesit", $vlerat);
        return $rezultati;
    }
}

Fillimisht kemi konvertuar ne statike variablin $db. Duke qene se eshte statike, ne konstruktor kemi perdorur deklaraten self::db per t'i dhene vlere. Arsyeja pse duhet te kthejme variablin $db ne statike eshte se ky variabel perdoret ne metodat getPunonjes(...) dhe shtoPunonjes(...) , te cilat do te jene statike. Detyrimisht nuk mund te perdorim $this->db ne nje metode statike, ndaj na duhet qe $db te jete po ashtu statike.

Pasi kemi konvertuar metoden getPunonjes(...) ne statike, detyrimisht kemi hequr variablin special $this, dhe kemi krijuar nje objekt te ri te klases Punonjes, i kemi dhene vlere variablave anetare te tij dhe e kemi kthyer me return.

Shtojme nje punonjes ne databaze:

<?php

$punonjes = new Punonjes();
$punonjes->emri = "Alban";
$punonjes->mbiemri = "Alban";
$punonjes->ditelindja = "1991-12-06";

//Therritja e metodes statike:

echo Punonjes::shtoPunonjes($punonjes)        //Rezultati:    1

Marrim punonjesin me id = 1 nga databaza:

<?php

//Do te na ktheje nje instance te klases Punonjes:

$punonjes = Punonjes::getPunonjes(1);

results matching ""

    No results matching ""